package com.example.file_management.service;

import com.example.file_management.mapper.material.ResourceMapper;
import com.example.file_management.mapper.material.TaskMapper;
import com.example.file_management.pojo.material.Resource;
import com.example.file_management.pojo.material.Resource.ResourceType;
import com.example.file_management.pojo.material.ResourceTypeStats;
import com.example.file_management.utils.FileConverter;
import com.itextpdf.text.Image;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.PdfWriter;
// 移除以下导入
// import javax.swing.text.Document;

// 确保只导入 iText 的 Document 类
import com.itextpdf.text.Document;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.FileStore;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ResourceService {

    private final ResourceMapper resourceMapper;
    private final TaskMapper taskMapper;
    private static final String UPLOAD_DIR = "E:/filestest/";
    private static final Logger logger = LoggerFactory.getLogger(ResourceService.class);

    @Autowired
    public ResourceService(ResourceMapper resourceMapper, TaskMapper taskMapper ) {
        this.resourceMapper = resourceMapper;
        this.taskMapper = taskMapper;
    }

    static {
        File dir = new File(UPLOAD_DIR);
        if (!dir.exists()) {
            dir.mkdirs();
        }
    }

    //查看同一文件的所有版本
    public List<Resource> getFileVersions(String taskName, String fileName) {
        return resourceMapper.getFileVersions(taskName, fileName);
    }

    // 📤 上传文件（带版本管理）
    public String uploadFile(MultipartFile file, String taskName) {
        try {
            // 1. 根据任务名称查询任务ID
            Long taskId = resourceMapper.selectTaskIdByTaskName(taskName);
            if (taskId == null) {
                return "错误：任务名称不存在 '" + taskName + "'";
            }

            // 2. 获取原始文件名 & 扩展名
            String originalFileName = file.getOriginalFilename();
            assert originalFileName != null;
            String fileExtension = originalFileName.substring(originalFileName.lastIndexOf(".")).toLowerCase();
            String uniqueFileName = UUID.randomUUID() + fileExtension;

            // 3. 获取最新版本号（改为使用taskId查询）
            int latestVersion = resourceMapper.getLatestVersion(taskId, originalFileName);
            int newVersion = latestVersion + 1;

            // 4. 确定文件存储路径
            Path filePath = Paths.get(UPLOAD_DIR, uniqueFileName);
            Files.write(filePath, file.getBytes());

            // 5. 解析文件类型
            ResourceType resourceType = determineFileType(fileExtension);

            // 6. 存入数据库（包含任务ID）
            Resource resource = new Resource();
            resource.setTaskId(taskId);// 新增任务ID
            resource.setTaskName(taskName);
            resource.setResourceName(originalFileName);
            resource.setResourceType(resourceType);
            resource.setFilePath(filePath.toString());
            resource.setUploadTime(LocalDateTime.now());
            resource.setVersion(newVersion);

            resourceMapper.insertDocument(resource);

            return "文件上传成功: " + originalFileName + " (版本 " + newVersion + ") 任务ID: " + taskId;
        } catch (IOException e) {
            return "文件上传失败: " + e.getMessage();
        }
    }

    // 📥 下载文件（获取最新版本）
    public byte[] downloadFile(String taskName, String fileName, Integer version) throws IOException {
        // 假设resourceMapper.getFileVersions(taskName, fileName)返回该文件所有版本的列表，按版本号降序排序
        List<Resource> fileVersions = resourceMapper.getFileVersions(taskName, fileName);

        if (fileVersions.isEmpty()) {
            throw new IOException("文件不存在: " + fileName);
        }

        // 根据提供的版本号查找对应版本的文件路径
        String filePathToDownload = null;
        for (Resource resource : fileVersions) {
            if (resource.getVersion().equals(version.toString())) { // 假定getVersion()返回String类型
                filePathToDownload = resource.getFilePath();
                break;
            }
        }

        if (filePathToDownload == null) {
            throw new IOException("未找到指定版本的文件: 版本" + version);
        }

        return Files.readAllBytes(Paths.get(filePathToDownload));
    }

    // 🗑️ 删除文件（支持删除特定版本或所有版本）
    public boolean deleteFile(String taskName, String fileName, Integer version) {
        try {
            if (version == null) {
                // 删除所有版本
                resourceMapper.deleteAllVersions(taskName, fileName);
            } else {
                // 删除特定版本
                resourceMapper.deleteSpecificVersion(taskName, fileName, version);
            }
            return true;
        } catch (Exception e) {
            logger.error("删除文件失败: {} (版本: {})", fileName, version, e);
            return false;
        }
    }

    // 📜 获取任务的所有资源（带版本）
    public List<Resource> getResourcesByTaskName(String taskName) {
        try {
            return resourceMapper.getResourcesByTaskName(taskName);
        } catch (Exception e) {
            logger.error("获取任务资源失败: {}", taskName, e);
            throw new RuntimeException("查询失败", e);
        }
    }


    // ⏳ 版本回滚（回滚到旧版本并创建新版本）
    public boolean rollbackFileVersion(String taskName, String fileName, int targetVersion) {
        try {
            resourceMapper.rollbackToVersion(taskName, fileName, targetVersion);
            return true;
        } catch (Exception e) {
            logger.error("回滚失败: {} 到版本 {}", fileName, targetVersion, e);
            return false;
        }
    }

    // 👀 预览文件（动态转换 PDF）
    public File previewFile(String taskName, String fileName) throws Exception {
        List<Resource> fileVersions = resourceMapper.getFileVersions(taskName, fileName);
        if (fileVersions.isEmpty()) {
            throw new Exception("文件不存在：" + fileName);
        }

        Path originalFilePath = Paths.get(fileVersions.get(0).getFilePath());

        if (!Files.exists(originalFilePath)) {
            throw new Exception("文件不存在：" + fileName);
        }

        // 解析文件类型
        String extension = getFileExtension(fileName).toLowerCase();
        ResourceType fileType = determineFileType(extension);

        if (fileType == ResourceType.IMAGE) {
            // 将图片转换为 PDF 文件
            return convertImageToPdf(originalFilePath.toFile(), fileName);
        }

        if (!fileName.matches(".*\\.(doc|docx|xls|xlsx|ppt|pptx|txt|csv|pdf)$")) {
            throw new Exception("该文件类型不支持预览");
        }

        // 生成 PDF 预览文件
        String pdfFileName = fileName.replaceFirst("\\.[^.]+$", ".pdf");
        Path pdfFilePath = Paths.get(UPLOAD_DIR, pdfFileName);

        if (!Files.exists(pdfFilePath)) {
            FileConverter.convertToPDF(originalFilePath.toString(), pdfFilePath.toString());
        }

        return pdfFilePath.toFile();
    }

    // 📌 解析文件类型
    private static final Set<String> IMAGE_TYPES = Set.of(".jpg", ".jpeg", ".png", ".gif", ".bmp", ".svg");
    private static final Set<String> VIDEO_TYPES = Set.of(".mp4", ".avi", ".mov", ".wmv", ".flv");
    private static final Set<String> DOC_TYPES = Set.of(".doc", ".docx", ".pdf", ".txt");
    private static final Set<String> SHEET_TYPES = Set.of(".xls", ".xlsx", ".csv");

    private ResourceType determineFileType(String extension) {
        if (IMAGE_TYPES.contains(extension)) return ResourceType.IMAGE;
        if (VIDEO_TYPES.contains(extension)) return ResourceType.VIDEO;
        if (DOC_TYPES.contains(extension)) return ResourceType.DOCUMENT;
        if (SHEET_TYPES.contains(extension)) return ResourceType.SPREADSHEET;
        return ResourceType.OTHER;
    }

    private String getFileExtension(String fileName) {
        int index = fileName.lastIndexOf(".");
        if (index >= 0) {
            return fileName.substring(index);
        }
        return "";
    }

    // 新增存储空间计算方法
    private File convertImageToPdf(File imageFile, String fileName) throws Exception {
        String pdfFileName = fileName.replaceFirst("\\.[^.]+$", ".pdf");
        Path pdfFilePath = Paths.get(UPLOAD_DIR, pdfFileName);


        // 使用 iText 将图片转换成 PDF
        Document document = (Document) new com.itextpdf.text.Document();

        PdfWriter writer = PdfWriter.getInstance((com.itextpdf.text.Document) document, new FileOutputStream(pdfFilePath.toFile()));
        document.open();

        // 创建 Image 对象，注意路径需要使用绝对路径
        Image image = Image.getInstance(imageFile.getAbsolutePath());
        image.scaleToFit(PageSize.A4.getWidth(), PageSize.A4.getHeight());

        // 将图片添加到 PDF 中
        document.add(image);
        document.close();
        writer.close();

        return pdfFilePath.toFile();
    }

    public Map<String, Object> getStorageInfo() throws IOException {
        Path storagePath = Paths.get(UPLOAD_DIR);

        // 计算已用空间（精确到字节）
        long usedBytes = Files.walk(storagePath)
                .filter(p -> p.toFile().isFile())
                .mapToLong(p -> p.toFile().length())
                .sum();

        // 获取存储分区的总空间
        FileStore store = Files.getFileStore(storagePath);
        long totalBytes = store.getTotalSpace();

        // 转换为GB（保留两位小数）
        double usedGB = usedBytes / (1024.0 * 1024 * 1024);
        double totalGB = totalBytes / (1024.0 * 1024 * 1024);

        // 计算使用百分比（保留两位小数）
        double percentage = Math.round((usedGB / totalGB) * 10000) / 100.0;

        return Map.of(
                "used", Math.round(usedGB * 100) / 100.0, // 保留两位小数
                "total", Math.round(totalGB * 100) / 100.0,
                "percentage", percentage
        );
    }
//文件分类管理就这一坨
    private static final Map<String, String> CATEGORY_DISPLAY = Map.of(
            "DOCUMENT", "文件:📄",
            "IMAGE", "图像:🖼️",
            "VIDEO", "视频、音频:🎬",
            "OTHER", "其他:📁"
    );

    public List<Map<String, Object>> getFileCategories() {
        List<ResourceTypeStats> dbStats = resourceMapper.getCategoryStatistics();


        Map<String, CategoryData> categories = Arrays.stream(new String[]{"DOCUMENT", "IMAGE", "VIDEO", "OTHER"})
                .collect(Collectors.toMap(
                        type -> type,
                        type -> new CategoryData(type, 0.0, null)
                ));

        dbStats.forEach(res -> {
            String categoryType = res.getResourceType();
            CategoryData data = categories.get(categoryType);
            if (data != null) {
                // 修复：将 orElse(0.0) 替换为 orElse(0L)，并显式转换为 double
                data.sizeBytes += Optional.ofNullable(res.getSize()).orElse(0L).doubleValue();
                LocalDateTime lastUpload = res.getUploadTime();
                if (lastUpload != null && (data.lastUpdate == null || lastUpload.isAfter(data.lastUpdate))) {
                    data.lastUpdate = lastUpload;
                }
            }
        });



        return categories.values().stream()
                .map(data -> Map.of(
                        "type", (Object) data.type, // 明确指定为Object类型
                        "name", (Object) CATEGORY_DISPLAY.get(data.type).split(":")[0],
                        "iconText", (Object) CATEGORY_DISPLAY.get(data.type).split(":")[1],
                        "size", (Object) formatSize((float) data.sizeBytes),
                        "lastUpdate", (Object) formatTime(data.lastUpdate)
                ))
                .collect(Collectors.toList());
    }

    private static class CategoryData {
        String type;
        double sizeBytes;
        LocalDateTime lastUpdate;

        CategoryData(String type, double sizeBytes, LocalDateTime lastUpdate) {
            this.type = type;
            this.sizeBytes = sizeBytes;
            this.lastUpdate = lastUpdate;
        }
    }

    private String formatSize(float bytes) {
        return bytes == 0 ? "0.00 GB" : String.format("%.2f GB", bytes / (1024.0 * 1024 ));
    }

    private String formatTime(LocalDateTime time) {
        return time == null ? "暂无数据" : time.format(DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm"));
    }
    //根据文件名称查询文件
    public List<Resource> getResourcesByFileName(String fileName) {
        try {
            return resourceMapper.getResourcesByFileName(fileName);
        } catch (Exception e) {
            logger.error("根据文件名称查询文件失败: {}", fileName, e);
            throw new RuntimeException("查询失败", e);
        }
    }
}